from django.shortcuts import render

# Create your views here.
from rest_framework import viewsets, status
from rest_framework.response import Response
from rest_framework.exceptions import AuthenticationFailed
# from rest_framework.pagination import PageNumberPagination
from django.db.models import Q

from datetime import datetime, date, timezone
import traceback

from apps.homepage.models import ZtTestReport, ZtTestTask, ZtUser
from .serializers import ZtTaskDetailSerializer

import time
from functools import wraps

def timing_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"Function {func.__name__!r} executed in {(end_time - start_time)*1000:.2f}ms")
        return result
    return wrapper

#判断是否登录
def has_permission(request):

    # session没有token，则未登录
    session_token = request.session.get('token')
    if not session_token:
        return False

    # 如果未传入token，则未登录
    request_token = request.META.get('HTTP_TOKEN')
    if not request_token:
        return False

    #如果都传入，则比对是否一致
    if session_token == request_token:
        return True
    else:
        return False

#所有开发甘特图数据
class GanttListViewSet(viewsets.ViewSet):

    def initial(self, request, *args, **kwargs):
        super(GanttListViewSet, self).initial(request, *args, **kwargs)
        # 检查用户是否登录
        if not has_permission(request):
            # 如果用户未登录，抛出 AuthenticationFailed 异常
            raise AuthenticationFailed({'code': 0, 'msg': '未登录'})

    #甘特图数据
    # def gantt(self, request, *args, **kwargs):
    #     '''
    #     根据项目id、功能模块id查询对应的需求
    #     '''
    #     try:
    #
    #         #获取参数
    #         project_id = self.request.query_params.get('project_id', None)
    #
    #         #如果project_id没有传
    #         if not project_id:
    #             return Response({'code': 0, 'msg': '没有携带项目id'}, status=status.HTTP_400_BAD_REQUEST)
    #
    #         # 搜索条件
    #         # 初始化一个空的查询集
    #         query = Q()
    #         query &= Q(project__id=project_id)  # 根据项目id查询需求
    #         query &= Q(project__deleted='0')  # 项目不能被删除
    #         query &= Q(deleted='0')  # 需求不能被删除
    #
    #         test_reports = ZtTestReport.objects.filter(query).distinct()
    #
    #         # _status = '未开始'  #默认为未开始
    #         # 梳理父子结构
    #         test_report_dict = {}
    #         all_names = set()
    #
    #         for test_report in test_reports:
    #
    #             # 获取成员用户名
    #             owner = test_report.owner
    #             members = test_report.members
    #             persons = set([owner] + members.split(','))
    #
    #             # 收集所有用户名
    #             all_names |= persons
    #
    #
    #             test_report_node = {
    #                 "id": test_report.id,
    #                 'name': test_report.title,
    #                 'members': persons,
    #             }
    #
    #             test_report_dict[test_report.id] = test_report_node
    #
    #         #查询真实姓名
    #         name_map = {}
    #         users = ZtUser.objects.filter(account__in=all_names).values('account', 'realname')
    #         for user in users:
    #             name_map[user['account']] = user['realname']
    #
    #         #处理搜索结果为真实姓名
    #         for key, value in test_report_dict.items():
    #             members = value['members']
    #             members_realname = [name_map[member] for member in members]
    #             value['members'] = ';'.join(members_realname)
    #             test_report_dict[key] = value
    #
    #         # return Response({'code': 1, 'msg': '获取成功', 'data': list(module_tree.values())})
    #         return Response({'code': 1, 'msg': '获取成功', 'data': list(test_report_dict.values())})
    #     except:
    #         print(traceback.format_exc())
    #         return Response({'code': 0, 'msg': '获取失败'},status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    # 列表数据
    @timing_decorator
    def list(self, request, *args, **kwargs):
        '''
        根据项目id、功能模块id、需求id查询对应的需求,还可根据名称、状态、指派人进行搜索
        '''
        try:
            # 获取参数
            project_id = self.request.query_params.get('project_id', None)
            execution_id = self.request.query_params.get('execution_id', None)

            # 如果project_id没有传
            if not project_id:
                return Response({'code': 0, 'msg': '没有携带项目id'}, status=status.HTTP_400_BAD_REQUEST)

            # 搜索条件
            # 初始化一个空的查询集
            query = Q()
            query &= Q(project__id=project_id)  # 根据项目id查询需求
            query &= Q(project__deleted='0')  # 项目不能被删除
            query &= Q(deleted='0')  # 需求不能被删除

            # 如果有执行id
            if execution_id:
                query &= Q(execution=execution_id)  # 对应执行的任务

            test_reports = ZtTestReport.objects.filter(query).select_related('execution').distinct()

            # _status = '未开始'  #默认为未开始
            # 梳理父子结构
            test_report_dict = {}
            team = set()
            all_tasks = set()

            for test_report in test_reports:

                # 获取成员用户名
                owner = test_report.owner
                members = test_report.members
                persons = set([owner] + members.split(','))

                # 收集所有用户名
                team |= persons

                #收集所有测试单
                tasks = set(test_report.tasks.split(','))
                all_tasks |= tasks

                # 获取执行版本
                execution = test_report.execution
                if execution:
                    execution_name = '#{} {}'.format(execution.id, execution.name)
                else:
                    execution_name = ''

                test_report_node = {
                    "id": test_report.id,
                    'name': test_report.title,
                    'members': persons,
                    'execution': execution_name,
                    'tasks': tasks,
                }

                test_report_dict[test_report.id] = test_report_node

            # 查询真实姓名
            name_map = {}
            users = ZtUser.objects.filter(account__in=team).values('account', 'realname')
            for user in users:
                name_map[user['account']] = user['realname']

            #查询测试单的名称
            test_task_map = {}
            test_tasks = ZtTestTask.objects.filter(id__in=all_tasks).values('id', 'name')
            for test_task in test_tasks:
                test_task_map[test_task['id']] = '#{} {}'.format(test_task['id'], test_task['name'])

            # 处理搜索结果为真实姓名及测试单名称
            for key, value in test_report_dict.items():
                members = value['members']
                members_realname = [name_map[member] for member in members]
                value['members'] = ';'.join(members_realname)

                tasks = value['tasks']
                tasks_realname = [test_task_map[int(task)] for task in tasks]
                value['tasks'] = ';'.join(tasks_realname)
                test_report_dict[key] = value

            # return Response({'code': 1, 'msg': '获取成功', 'data': list(module_tree.values())})
            return Response({'code': 1, 'msg': '获取成功', 'data': list(test_report_dict.values())})
        except:
            print(traceback.format_exc())
            return Response({'code': 0, 'msg': '获取失败'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

#测试单详细数据
class DetailViewSet(viewsets.ViewSet):
    # queryset = ZtTask.objects
    # serializer_class = ZtTaskDetailSerializer

    def initial(self, request, *args, **kwargs):
        super(DetailViewSet, self).initial(request, *args, **kwargs)
        # 检查用户是否登录
        if not has_permission(request):
            # 如果用户未登录，抛出 AuthenticationFailed 异常
            raise AuthenticationFailed({'code': 0, 'msg': '未登录'})

    #格式化数据
    @timing_decorator
    def list(self, request, *args, **kwargs):
        '''
        根据项目id、功能模块id查询对应的开发任务
        '''
        try:
            #获取参数
            test_report_id = self.request.query_params.get('test_report_id', None)

            # 如果test_report_id没有传
            if not test_report_id:
                return Response({'code': 0, 'msg': '未携带测试报告id'}, status=status.HTTP_400_BAD_REQUEST)

            test_report = ZtTestReport.objects.filter(id=test_report_id).select_related('execution').distinct().first()

            # 未查询到
            if not test_report:
                return Response({'code': 0, 'msg': '该测试报告不存在'})

            # _status = '未开始'  #默认为未开始
            # 梳理父子结构
            team = set()
            all_tasks = set()

            # 获取成员用户名
            owner = test_report.owner
            members = test_report.members
            persons = set([owner] + members.split(','))

            # 收集所有用户名
            team |= persons

            # 收集所有测试单
            tasks = set(test_report.tasks.split(','))
            all_tasks |= tasks

            # 获取执行版本
            execution = test_report.execution
            if execution:
                execution_name = '#{} {}'.format(execution.id, execution.name)
            else:
                execution_name = ''

            test_report_node = {
                "id": test_report.id,
                'name': test_report.title,
                'members': persons,
                'report': test_report.report,
                'execution': execution_name,
                'tasks': tasks
            }

            # 查询真实姓名
            name_map = {}
            users = ZtUser.objects.filter(account__in=team).values('account', 'realname')
            for user in users:
                name_map[user['account']] = user['realname']

            # 查询测试单的名称
            test_task_map = {}
            test_tasks = ZtTestTask.objects.filter(id__in=all_tasks).values('id', 'name')
            for test_task in test_tasks:
                test_task_map[test_task['id']] = '#{} {}'.format(test_task['id'], test_task['name'])

            # 处理搜索结果为真实姓名及测试单名称
            members = test_report_node['members']
            members_realname = [name_map[member] for member in members]
            test_report_node['members'] = ';'.join(members_realname)

            tasks = test_report_node['tasks']
            tasks_realname = [test_task_map[int(task)] for task in tasks]
            test_report_node['tasks'] = ';'.join(tasks_realname)

            # return Response({'code': 1, 'msg': '获取成功', 'data': list(module_tree.values())})
            return Response({'code': 1, 'msg': '获取成功',
                             'data': {'teamCount': len(team), 'detail': test_report_node}})
        except:
            print(traceback.format_exc())
            return Response({'code': 0, 'msg': '获取失败'},status=status.HTTP_500_INTERNAL_SERVER_ERROR)